/**
 * RulesServiceImpl.java
 * @author
 * 作者 屈甲康 
 */
package org.jackysoft.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.util.Version;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFTextStripper;
import org.jackysoft.entity.nosql.Rules;
import org.jackysoft.portal.cfg.PortalConfiguration;
import org.jackysoft.service.AbstractNoSqlServiceImpl;
import org.jackysoft.service.RulesService;
import org.jackysoft.util.IOUtils;
import org.jackysoft.util.Office2PDF;
import org.jackysoft.util.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.wltea.analyzer.lucene.IKAnalyzer;
import org.wltea.analyzer.lucene.IKQueryParser;

import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

@Service
@Transactional
public class RulesServiceImpl extends AbstractNoSqlServiceImpl<Rules> implements
		RulesService {

	static final Log logger = LogFactory.getLog(RulesServiceImpl.class);

	private PortalConfiguration portalConfig;
	/**
	 * 
	 */
	private static final long serialVersionUID = -1293256543108774136L;

	public RulesServiceImpl() {
		this.type = Rules.class;
	}


	@Override
	public Collection<Rules> gets(int start, int size)
			throws DataAccessException {
		DBObject sort = new BasicDBObject("updateDate","desc");
		return this.gets(start, size, sort);
	}

	
	@Override
	public void create(Rules bean, File file, String fileName)
			throws DataAccessException, InterruptedException,
			ExecutionException {
		String path = File.separator + "attachment" + File.separator;
		String relativeUrl = "/attachment/";
		String ext = StringUtils.splitPostFileName(fileName);
		String name = "";
		byte[] data = IOUtils.toByteArray(file);
		logger.info("开始传送文件 :" + fileName);
		Office2PDF wpf = new Office2PDF(config.getPdfServer(),
				config.getPdfServerPort(), ext, data);
		ExecutorService executor = Executors.newSingleThreadExecutor();
		Future<String> future = executor.submit(wpf);
		name = future.get() + ".pdf";
		executor.shutdown();
		relativeUrl += name;

		logger.info("传送文件 :" + fileName + " 完成" + ", 文件名: " + name);

		String fullName = path + name;
		if(bean==null)bean = new Rules();
		bean.setUpdateDate(new Date());
		bean.setName(fileName);
		bean.setRealName(fullName);
		bean.setRelativePath(relativeUrl);
		super.save(bean);
	}

	@Override
	public void reindex() throws DataAccessException, IOException {
		//portalConfig.removeDir(portalConfig.getIndexDir());
		String filePath = portalConfig.getFileDir();
		logger.info(filePath);
	
		String indexPath = portalConfig.getIndexDir();
		logger.info(indexPath);
		/* 指明要索引文件夹的位置,这里是d盘的s文件夹下 */
		File fileDir = new File(filePath);

		/* 这里放索引文件的位置 */
		Directory indexDir = new NIOFSDirectory(new File(indexPath));
		Analyzer luceneAnalyzer = new IKAnalyzer();
		IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_31,
				luceneAnalyzer);
		conf.setOpenMode(OpenMode.CREATE_OR_APPEND);
		IndexWriter indexWriter = new IndexWriter(indexDir, conf);
		long startTime = new Date().getTime();

		Collection<Rules> rules = gets();

		// 增加document到索引去
		for (Rules r : rules) {
			logger.info(r.getName() + " 正在被索引.");

			/*
			 * 注意要变的就是这里，路径和读取文件的方法
			 */
			String path = r.getRelativePath();
			String content = readPdf(path);
			String name = r.getName();
			// readWord(path);
			// String path ="d:\\s\\index.htm";
			// String temp = ReadFile.readHtml(path);
			Document document = new Document();

			Field FieldId = new Field("name", name, Field.Store.YES,
					Field.Index.ANALYZED);

			Field FieldPath = new Field("path", path, Field.Store.YES,
					Field.Index.ANALYZED);

			Field Fielddigest = new Field("digest", content, Field.Store.YES,
					Field.Index.ANALYZED,
					Field.TermVector.WITH_POSITIONS_OFFSETS);
			Field FieldBody = new Field("body", content, Field.Store.YES,
					Field.Index.ANALYZED,
					Field.TermVector.WITH_POSITIONS_OFFSETS);
			document.add(FieldId);
			document.add(FieldPath);
			document.add(FieldBody);
			document.add(Fielddigest);
			indexWriter.addDocument(document);
		}

		// optimize()方法是对索引进行优化
		indexWriter.optimize();
		indexWriter.close();

		// 测试一下索引的时间
		long endTime = new Date().getTime();
		logger.info("这花费了" + (endTime - startTime) + " 毫秒来把文档增加到索引里面去!"
				+ fileDir.getPath());

	}

	public PortalConfiguration getPortalConfig() {
		return portalConfig;
	}

	@Resource
	public void setPortalConfig(PortalConfiguration portalConfig) {
		this.portalConfig = portalConfig;
	}

	
	public String readPdf(String path) throws IOException {

		String appBase = System.getProperty("appBase");
		StringBuffer content = new StringBuffer("");// 文档内容
		FileInputStream fis = new FileInputStream(appBase+File.separator+path);
		PDFParser p = new PDFParser(fis);
		p.parse();
		PDFTextStripper ts = new PDFTextStripper();
		PDDocument pdoc = p.getPDDocument();
		/*
		 * if(pdoc.isEncrypted()){ pdoc.decrypt("123456"); }
		 */
		String cnt = ts.getText(pdoc);
		content.append(cnt);
		fis.close();
		pdoc.close();
		return content.toString().trim();
	}

	public Collection<Rules> search(String q) throws Exception {

		Collection<Rules> results = Lists.newArrayList();
		logger.info("开始搜索...........\n\n\n");
		// 搜索内容自己换
		String queryString = q;
		Directory indexDir = new NIOFSDirectory(new File(
				portalConfig.getIndexDir()));
		IndexReader indexReader = IndexReader.open(indexDir);

		IndexSearcher searcher = new IndexSearcher(indexReader); // 这里注意索引存放的路径

		Query query = null;
		Analyzer analyzer = new IKAnalyzer();
		try {
			/*QueryParser qp = new QueryParser(Version.LUCENE_31, "body",
					analyzer);
			query = qp.parse(queryString);*/
			
			//query  =IKQueryParser.parse("body", queryString); 
			query  =IKQueryParser.parseMultiField(new String[]{"body","name"}, queryString); 
			//TODO 搜索引擎优化...
		} catch (Exception e) {
			logger.error(e);
			e.printStackTrace();
		}
		if (searcher != null) {

			TopDocs tds = searcher.search(query, 20);

			int totalHits = tds.totalHits;

			logger.info("命中 " + totalHits);

			ScoreDoc[] hits = tds.scoreDocs;

			for (ScoreDoc sd : hits) {
				Document hitDoc = searcher.doc(sd.doc);
				
				String name = hitDoc.get("name");
				String path = hitDoc.get("path");
				String text = hitDoc.get("body");
				
				SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(
						"<font color='red'>", "</font>");
				Highlighter highlighter = new Highlighter(simpleHTMLFormatter,
						new QueryScorer(query));
				highlighter.setTextFragmenter(new SimpleFragmenter(80));
				Rules rules = new Rules();
				rules.setName(name);
				rules.setRelativePath(path);
				
				if (text != null) {
					TokenStream tokenStream = analyzer.tokenStream("digest",new StringReader(text));
					String highLightText = highlighter.getBestFragment(tokenStream, text);
					rules.setDigest(highLightText);
				
				}
				
				results.add(rules);

			}

			logger.info(tds.totalHits);
			logger.info("搜索完成...........\n\n\n");
			searcher.close();
		}
		return results;

	}

}